#ifndef __IASSISTGEN2_UIEVENTROUTER_H
#define __IASSISTGEN2_UIEVENTROUTER_H

#define ASYNC_EVENT_PROCESSOR_POOL_SIZE 10
#define DEFAULT_SOCKET_RECV_BUFLEN		16384
#define MAX_PAIR_EVENT_NUM				64

#pragma once
#include <map>
#include <list>
#include <string>
#include <pthread.h>
#include <string.h>
#include <arpa/inet.h>

#include "UIEvent.h"
#include "UIOSAL.h"
#include "UIModule.h"

void* asyncEventProcess(void* lpParam);
void* syncEventProcessLoop(void* lpParam);
void* syncDataProcessLoop(void* lpParam);

class UIModule;

typedef struct {
	UIModule* module;
	UIEvent*  event;
} UIEventProcessorInfo;

/*
class UIAsyncEventProcessor
{
public:
	UIAsyncEventProcessor(UIModule* module);
	~UIAsyncEventProcessor(void);

	void processEvent(UIEvent* event);
	void cancel(void);
	
private:
	pthread_t eventProcessThreadPool[ASYNC_EVENT_PROCESSOR_POOL_SIZE];
	UIModule* m_module;
};
*/

class UISyncEventProcessor
{
public:
	UISyncEventProcessor(UIModule* module);
	~UISyncEventProcessor(void);
	
	UIEvent* getFirstEvent(void); 
	UIModule* getModule(void);
	void addEvent(UIEvent* event);
	void cancel(void);
	
private:
	pthread_t eventProcessThread;
	UIModule* m_module;
	std::list<UIEvent*> m_eventQueue;
};

class UISyncDataProcessor
{
public:
	UISyncDataProcessor(UIModule* module);
	~UISyncDataProcessor(void);
	
	UIEvent* getFirstData(void); 
	UIModule* getModule(void);
	void addData(UIEvent* event);
	void cancel(void);
	
private:
	pthread_t dataProcessThread;
	UIModule* m_module;
	std::list<UIEvent*> m_dataQueue;
};

/*
class UISocketMessage
{
public:
	enum { header_length = 9 };
	UISocketMessage() : body_length_(0)
	{
		data_=std::vector<char>(header_length);
	}
	
	const char* data() const			{	return (char*)&data_[0];				}
	char* data()						{	return (char*)&data_[0];				}
	char* data(int index) {
		if (index >= 0 && index < header_length + body_length_)
			return (char*)&data_[index];
	}
	
	size_t length() const				{	return header_length + body_length_;	}
	
	const char* body() const			{	return (char*)&data_[header_length];	}
	char* body()						{	return (char*)&data_[header_length];	}
	char* body(int index) {
		if (index >= 0 && index < body_length_)
			return (char*)&data_[header_length+index];
	}

	char type() const					{	return type_;							}
	void type(char type)				{	type_ = type;							}

	size_t time() const					{	return time_;							}
	void time(size_t time)				{	time_ = time;							}

	size_t body_length() const			{	return body_length_;					}
	void body_length(size_t length)	
	{	
		body_length_ = length;
		if(header_length+body_length_>data_.size())
			data_.resize(body_length_+header_length);
	}
	
	bool decode_header()
	{
		using namespace std; // For strncat and atoi.

		memcpy(&type_,&data_[0],1);
		
		size_t n_time;
		memcpy(&n_time,&data_[1],4);
		time_ = ntohl(n_time);

		size_t n_body_length;
		memcpy(&n_body_length,&data_[5],4);
		body_length_ = ntohl(n_body_length);

		if(header_length+body_length_>data_.size())
			data_.resize(body_length_+header_length);
		return true;
	}

	void encode_header()
	{
		using namespace std;
		char header[header_length+1];
		header[0] = type_;
		
		size_t n_time = htonl(time_);
		memcpy(&header[1], &n_time, 4);

		size_t n_body_length = htonl(body_length_);
		memcpy(&header[5], &n_body_length, 4);

		memcpy(&data_[0], header, header_length);
	}

private:
	std::vector<char> data_;
	size_t body_length_;
	char type_;
	size_t time_;
};
*/

/*

void* socketListening(void* lpParam);
void* clientSocketAccept(void* lpParam);

class UIEventSocketService
{
public:
	UIEventSocketService(void);
	~UIEventSocketService(void);
	virtual void sendEvent(UIEvent* event)	= 0;
	virtual void startListening(void)		= 0;
	virtual bool initialize(void)			= 0;

protected:
	int sendAll(SOCKET socket, char *data, int* len);
	int genData(UIEvent* event, UISocketMessage* message);
};

class UIEventSocketServerService : public UIEventSocketService
{
public:
	UIEventSocketServerService(void);
	~UIEventSocketServerService(void);

	virtual void sendEvent(UIEvent* event);
	virtual void startListening(void);
	virtual bool initialize(void);
	
	SOCKET m_listenSocket;
	void addSocket(std::string addr, SOCKET socket);
	void addModuleAddr(UIModuleType moduleType, std::string moduleAddr) {
		m_moduleAddr[moduleType] = moduleAddr;
	}

private:
	std::map<std::string, SOCKET>	m_clientSockets;
	std::map<std::string, UIThread> m_listeningThreads;
	std::map<UIModuleType, std::string> m_moduleAddr;
	UIThread acceptThread;
};

class UIEventSocketClientService : public UIEventSocketService
{
public:
	UIEventSocketClientService(void);
	~UIEventSocketClientService(void);
	
	virtual void sendEvent(UIEvent* event);
	virtual void startListening(void);
	virtual bool initialize(void);

private:
	SOCKET m_Socket;
	UIThread listeningThread;
};

*/

typedef struct {
	UIEvent*  event;
	bool	  isReturned;
} UIPairedEventObject;

class UIEventRouter
{
public:
	static UIEventRouter* getInstance();
	static void release();

	bool sendEvent(UIEvent* event);
	bool sendSyncEvent(UIEvent* event, UIEvent &retEvent, int timeOutSecond);
	bool sendData(UIEvent* event);
	void registerModule(UIModuleType type, UIModule* module);

private:
	UIEventRouter(void);
	~UIEventRouter(void);
	static UIEventRouter* m_pInstance;

	bool isSyncEvent(UIModuleType module_type, std::string event_type);
	std::map<UIModuleType, UISyncEventProcessor*> m_syncEventProcessors;
	//std::map<UIModuleType, UIAsyncEventProcessor*> m_asyncEventProcessors;
	std::map<UIModuleType, UISyncDataProcessor*> m_syncDataProcessors;

	//UIEventSocketService*	m_pSocketService;
	
	UIPairedEventObject		m_pairedEventPool[MAX_PAIR_EVENT_NUM];
	std::map<int, int>		m_pairID2PoolIdx;
	int						m_currentPairID;
};

#endif
